perm filename FAIL.PMP[S,DOC] blob sn#078765 filedate 1973-12-20 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00014 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00003 00002	STANFORD ARTIFICIAL INTELLIGENCE PROJECT                 April 1970
C00004 00003	SAILON 26.2      FAIL MANUAL         FAIL STATEMENTS                1
C00021 00004	SAILON 26.2      FAIL MANUAL         FAIL STATEMENTS                5
C00034 00005	SAILON 26.2      FAIL MANUAL         FAIL STATEMENTS                9
C00044 00006	SAILON 26.2      FAIL MANUAL           PSEUDO-OPS                  12
C00059 00007	SAILON 26.2      FAIL MANUAL           PSEUDO-OPS                  16
C00065 00008	SAILON 26.2      FAIL MANUAL           PSEUDO-OPS                  18
C00072 00009	SAILON 26.2      FAIL MANUAL          MACROS (etc)                 20
C00079 00010	SAILON 26.2      FAIL MANUAL          MACROS (etc)                 22
C00084 00011	SAILON 26.2      FAIL MANUAL          MACROS (etc)                 23
C00087 00012	SAILON 26.2      FAIL MANUAL          MACROS (etc)                 24
C00101 00013	SAILON 26.2      FAIL MANUAL                                       29
C00104 00014	
C00105 ENDMK
C⊗;
STANFORD ARTIFICIAL INTELLIGENCE PROJECT                 April 1970
OPERATING NOTE No. 26.2
   
   
   
   
   
   
   
			FAIL MANUAL


			P. M. Petit







   
   
   
   
   
   
   
      The work reported here  was  supported  in  part  by  the
      Advanced  Research  Projects  Agency of the Department of
      Defense under contract SD-183.
SAILON 26.2      FAIL MANUAL         FAIL STATEMENTS                1

1.0	FAIL STATEMENTS


INTRODUCTION

FAIL is the good symbolic assembly program for the PDP-6  or  PDP-10.
This  assembler  performs  many  useful  and unique functions, making
machine language programming  easier,  faster,  and  more  efficient.
FAIL  is  a  one-pass  assembler, which means that it reads the input
file only once.  This and other efficiencies which have been employed
in  its  coding  make  FAIL  at least five times as fast as the other
leading brand of assembler for the PDP-10.

Basically, the assembler processes the  programmer's  source  program
statements  by  translating  mnemonic  operation  codes to the binary
codes needed in machine instructions,  relating  symbols  to  numeric
values,  assigning relocatable or absolute core addresses for program
instructions and  data,  and  preparing  an  output  listing  of  the
program,  which  includes  notification of any errors detected during
the assembly.

FAIL also has a powerful macro processor which allows the  programmer
to  create  new  language  elements,  thus expanding and adapting the
assembler to perform special functions for each programming job.

1.1 FAIL LANGUAGE -- STATEMENTS

A  FAIL  program consists of a string of statements, usually one to a
line, which is read from  one  or  more  input  files.   A  statement
usually  has  one  or  more  of  the  following elements, arranged as
follows:

LABEL:  OPERATOR OPERAND(s)  (carriage return-line feed)

A  statement  must contain at least one of these elements, or it is a
blank line.  Blank lines generate no  code  and  are  not  considered
statements.

The  binary  words  (code)  which the assembler translates statements
into, are normally placed in successively increasing  locations  when
they  are  loaded by the loader.  The assembler uses a counter called
the location counter to keep track of  the  location  into  which  it
should place the next word.  Each time the assembler generates a word
of binary from a statement, the location counter is increased by one.
The  location  counter thus contains the address of the location into
which the next word generated will be placed.

1.1.1 LABELS

A  label  is  the  symbolic  name,  created  by the source programmer
(that's you) to identify a location in the object  (binary)  program.
When  a  label  is  encountered,  the label is given the value of the
SAILON 26.2      FAIL MANUAL         FAIL STATEMENTS                2

address currently in the location counter.   This  means  that  if  a
statement  starts  with a label, the label (symbol) will be given the
value of the address  of  the  core  location  into  which  the  code
generated  for  that statement will be placed.  Hence that label will
refer to the statement it appears in.  See symbolic addresses below.

More than one label may appear on one line, in  which  case  all  are
given  the same value.  Note also that if a label (or several labels)
is the only thing on a line, the line will not generate any code, and
the  label  will  have the same value it would have if it appeared on
the next line instead.

A label need not be the first thing one a line.  It may appear  after
the operator, between operands, or at the end of the line.  In all of
these cases, the label will have the same value.  A label, of course,
cannot appear in a comment (see below).

A label consists of a symbol (see below) followed by a colon (:). One
or more spaces may appear between the symbol and the colon, and these
are ignored if present.

1.1.2 OPERATORS

An operator may  be  one  of  the  semi-infinite  number  of  machine
instruction mnemonics or UUO mnemonics (if an appendix appears at the
end of this write-up, there is probably a listing of these  mnemonics
there),  an  assembler  pseudo-op  (see  the pseudo-op section), or a
user-defined operation code (see  OPDEF  in  pseudo-op  section).  An
operator,  if it appears, must be the first thing on the line besides
labels  and/or  assignment  statements  (see  assignment  statements,
below).   If the first thing on a line (besides labels and assignment
statements) is not a defined operator (op-code, pseudo-op, or OPDEF),
it  is  assumed  by  the  assembler  to  be a symbolic reference (see
below).  That is, it is assumed that there is no operator.

The value of an op-code (machine  instruction  or  UUO  mnemonic)  is
placed  in the op-code field of the binary word being assembled.  The
effects of pseudo-ops and opdefs  are  listed  with  the  appropriate
pseudo-ops in that section.

1.1.3  OPERANDS

There are three types of operands which appear after an  op-code  (or
opdef).   (See the individual pseudo-op for the operands which appear
with it.) The three  types  are:  address  field,  index  field,  and
accumulator  (AC)  field.   An operand consists of an expression (see
below) accompanied by the characters, if any, which identify the type
of  field.  An  expression  which  is  followed,  immediately or with
intervening spaces, by a comma (,), is the  AC  (accumulator)  field,
and  its  value  is placed in the accumulator field of the word being
assembled.  An expression which is  enclosed,  in  its  entirety,  in
parentheses  is  the index field.  The right half (18 bits) is "ored"
SAILON 26.2      FAIL MANUAL         FAIL STATEMENTS                3

into the left half of the word being assembled.  If no address  field
has appeared on the line before the index field, the left half of the
value of the index field is placed in the right half (address  field)
of  the word being assembled.  An expression which is not followed by
a comma and not entirely enclosed in parentheses, and which is either
not defined as an operator or not the first thing on the line besides
labels or assignment statements, is an address field.  The  value  of
an  address  field is placed in the address field (right half) of the
word  being  assembled.   Only  one  address  field  is  allowed  per
statement.

1.1.4 COMMENTS

If a semi-colon (;) appears on a line, all characters between it  and
the  next  line feed are totally ignored by the assembler.  (The only
exceptions have to do with MCAROs and REPEAT,  etc.   See  the  macro
section.)  This  is  an  excellent  place  for  the programmer to put
comments and other forms of graffiti which  might  otherwise  confuse
the assembler.

1.1.5 OTHER NONSENSE

If one or more at-sign characters (@) appear as part of a  statement,
the  indirect  bit will be turned on in the word being assembled. The
at-sign(s) may appear anywhere on the line except in the  comment  or
imbedded inside symbols or expressions.

1.2 SYMBOLS

A symbol consists of a contiguous string of characters, the first  of
which  is  a letter and the others of which are letters or digits. In
addition to A-Z and a-z, the three characters $ % and . are  letters.
Any  two symbols which have the first six characters the same will be
considered as identical by the assembler.  In  fact,  any  characters
beyond the sixth will be truncated on input.  Symbols are also called
identifiers.

1.2.1 SYMBOLIC ADDRESSES

All  values,  including  addresses, have two parts.  The fist part is
the numeric value and the second is the relocation.  Most values have
relocations  of  either  1 or 0.  Values with 0 relocation are called
obsolute.  Numbers, such as 1 or 37,  are  absolute.  Values  with  a
relocation of 1 are called relocatable. Symbolic addresses (values of
labels) are usually relocatable. This  is  so  the  loader  can  load
programs anywhere in core.  When the loader starts to load a program,
it defines the "relocation constant" for that program.  This  is  the
absolute  location  which will be equivalent to relocatable 0, or, in
other words, the address at which the  loader  will,  under  ordinary
conditions,  place the first word of the program.  (Relocations other
than 1 or 0 may occur under certain circumstances.)  All  values  are
passed  to  the  loader along with relocation.  The loader multiplies
SAILON 26.2      FAIL MANUAL         FAIL STATEMENTS                4

the relocation by the relocation constant and adds the result to  the
numeric  value.   Thus  the  loader  can load a program anywhere, and
addresses will still refer to the words the programmer intended.

There are three ways a symbol may be given a value.  One  way  is  to
have  the  symbol appear as a label (i.e., appear on a line, followed
by a colon).  This usually gives the symbol a relocatable value.  The
second way to give a symbol a value is with the assignment statement.
An assignment statement consists of a symbol followed by a left arrow
(or  two  left  arrows)  followed  by  an expression.  This gives the
symbol the value of the  expression,  which  may  be  relocatable  or
absolute  or  may  have some other relocation.  Assignment statements
may appear anywhere a label may appear, and have  no  effect  on  the
rest  of the line they appear on.  More than one assignment statement
may appear on a line.

Also, more than one symbol may be given a value with  one  statement.
See last example below.

	A1 ← 7
	BQZRN ← 137 + 52 -22 * 3
	FONLY ← FOOBAZ +1
	GARP ← Foo ← BAZ ← ZOT ← Mumble ← 27

A symbol may be redefined  using  an  assignment  statement,  but  an
attempt to redefine a symbol as a label (with a colon) will result in
a multiple-definition error message and  the  retention  of  the  old
value.

If two left arrows are used with a symbol in an assignment statement,
that symbol will be defined in the normal  way,  but  in  the  symbol
table  which  DDT  will see, a bit will be turned on so that DDT will
not use that symbol in typing out expressions.  This is equivalent to
saying $K in DDT.

The third way of defining a symbol is by following one or more of its
uses with a number sign (#).  This makes the symbol  a  variable  and
the  assembler will set aside an empty cell with that name at the end
of the program (with the literals) unless the VAR pseudo-op  is  used
(see VAR).

	Examples:

	MOVEM A,FOO#
	MOVEI B,BAZ#-1

Variables defined this way are local  to  the  block  in  which  they
appear with the #.  Thus if FOO# appears in two blocks, two different
versions of FOO will be created.  If this is  not  desired,  see  the
INTEGER pseudo-op.
SAILON 26.2      FAIL MANUAL         FAIL STATEMENTS                5

1.2.2 SPECIAL CONSIDERATIONS

The symbol . (dot) has a special predefined value,  which  cannot  be
changed.   This  value  is that of the location counter, that is, the
value which would be given a label  if  it  appeared  on  that  line.
Thus:

FOO:	JRST FOO

is equivalent to

FOO:	JRST .

1.3 NUMBERS

The FAIL input scanner considers numbers to  be  in  base  8  (octal)
unless  the  radix  is changed using the RADIX pseudo-op.  (See RADIX
pseudo-op).  This pseudo-op may be used to set the input base (called
the  "current  radix")  to  almost  anything  else.   A  digit string
consists of a string of digits (0 to 9), and a number may be a single
digit  string, in which case its value as the value of that number in
the current radix.  A number may also consist of an  equal  sign  (=)
followed  by  a  digit string, in which case the digit string will be
interpreted in base 10 (decimal) regardless of the current radix.

	Examples:

	1743
	2
	=100

1.3.1 FLOATING POINT NUMBERS

Another  form  of  number  which  may be used with FAIL consists of a
digit-string (with at least one  digit)  followed  by  the  letter  .
(decimal point) followed by a digit string (which may be empty). This
number will be interpreted in base 10  (decimal)  regardless  of  the
current radix, and will be put into PDP-6/10 floating-point format.

A  floating  point  number  may  be  followed  by  an exponent.  This
consists of the letter E followed by an optional plus or minus  sign,
and  one or two digits.  The number following the E is interpreted in
base 10 (decimal) and the floating point number is multiplied by that
power of 10.

	Examples:

	10.7E1	(Equivalent to 107.0)
	9.973
	0.13
	10.
	1.86E05
SAILON 26.2      FAIL MANUAL         FAIL STATEMENTS                6

	31.4159E-1

1.3.2 BINARY SHIFTING

Any number may be followed by the letter B followed  by  one  or  two
digits.  The value of this new number will be that of the old number,
shifted (logically) until the low order bit is in the  indicated  bit
position. Thus, B35 will have no effect on the value of a number, and
B34 will shift left by one.  Note that the  number  following  the  B
will be interpreted in decimal.

	Examples:

	254B8
	1B33  (equivalent to 4)
	=10B27
	22B18

No number may have an  imbedded  space.   Therefore,  no  spaces  may
appear  between  successive  digits  in  a digit string, or between a
digit string and a B which is intended for shifting, or following the
B, or before or after the E of an exponent, etc.

1.3.3  ASCII and SIXBIT Numbers

A string consisting of a double-quote (") followed  by  a  string  of
characters  not  including  double-quote, followed by a double quote,
has the value of the right-adjusted 7-bit ascii for the characters in
the  string,  not  including  the  double  quotes.  If more than five
characters appear, the high-order parts of the  value  will  be  lost
(i.e.  the  value  is  only  the right-hand 36 bits).  Also, a string
consisting of a single quote (') followed by a string not  containing
single  quote,  followed  by  a  single  quote,  has the value of the
right-adjusted sixbit for the characters in the string.   Again,  the
high-order bits are lost if there are more than six characters.

Both  of these constructions are considered numbers, except that they
may not be followed by the B construction for shifting.

1.4 EXPRESSIONS

An expression consists of operands connected by operators.

1.4.1 Operators.

FAIL recognizes the following operators:

Symbol	Meaning			Priority Level

 +	PLUS			1
 -	(binary) MINUS		1
 *	TIMES			2
SAILON 26.2      FAIL MANUAL         FAIL STATEMENTS                7

 /	DIVIDED-BY		2
 ∧	AND			3
 ∨	OR			3
 ≠	XOR			3
 ⊗	LEFT-SHIFT (logical)	4
 -	(unary) MINUS
	 (two's complement)	5
 ¬	(unary) NOT
	 (one's complement)	5

Also,  since some of these characters can't be typed on the teletype,
the following equivalences are recognized by FAIL:

 &	same as ∧
 !	same as ∨
 ⊗	may be typed in as control V
 ≠ and ¬ have no teletype equivalents.  You lose.

1.4.2 Operands.

Operands   may   be  symbols,  numbers, or  expressions  enclosed  in
parentheses. They may  also  be  literals  (see  literals)  or  lines
enclosed  in  "pointy  brackets"  (or  brokets)  (<  >).  This latter
construction has the value of the 36-bit  word  which  the  assembler
would  generate  for the line inside the brokets, if it appeared on a
line by itself.  (In the case of pseudo-ops which generate more  than
one  word  of code, the value is the first word generated.) Note that
this construction does not, of itself, actually  generate  any  code.
For example, since the line:

	JRST 4,37

would generate the word 254200 000037, the value of the expression:

	<JRST 4,37> + 102

is:	254200 000141

This construction is particularly handy for such things as:

	MOVSI A, (<JRST 4,>)
	TLO B,(<MOVEI>)

1.4.3 Evaluation of Expressions.

The  operators  in  expressions  are  evaluated in order of priority.
Thus, first all unary operators are evaluated (NOT and unary  MINUS),
then  all  left shifts are evaluated, then all AND's, OR's and XOR's,
and so forth until all PLUS's and MINUS's have been  evaluated.  This
order  of  evaluateion  may  be  changed  by  the use of parentheses.
However, if the entire expression is enclosed in parentheses, it will
be   considered   to   be  the  index  field  (except  in  assignment
SAILON 26.2      FAIL MANUAL         FAIL STATEMENTS                8

statements).

1.4.4 Relocation and Definition.

Note  that the relocation for an expression may be other than 1 or 0.
For example, the relocation of the sum of two relocatable symbols  is
2.  In  fact,  in the case of multiplication, division, shifting, and
the logical operators, the  relocation  may  be  quite  difficult  to
evaluate. In all cases where the relocation of an expression is other
than 1 or 0, or is  difficult  to  evaluate,  the  assembler  instead
converts  the  expression to Polish and saves the Polish.  Under some
circumstances, the Polish may be passed to the loader for evaluation.
Under  other  circumstances,  the  assembler will evaluate it itself,
later.  In all cases, the right thing happens.

Also, an expression may contain symbols which are  defined  later  in
the program (called forward references), or which are external to the
program.  In these cases, the expression is difficult to evaluate and
the assembler again saves the Polish.

However,  the  saving of Polish takes up assembler core space rapidly
and, when the Polish must be passed to the loader,  the  binary  file
tends  to  get  long.   Therefore,  if either of these considerations
becomes important, care should be taken to avoid such expressions.

1.5 LITERALS (pronounced as though it had been misspelled LITTERALS).

A  literal  consists  of  a  left square bracket ([) followed by some
text,  followed  by  a  right  square  bracket  (]).   The  assembler
assembles  the  text  between  the  square  brackets  and  places the
generated code at the end of the program (unless the LIT pseudo-op is
used.  See LIT pseudo-op.) The value of the literal is the address at
which the generated code is placed.  If the text generates more  than
one word of code, the value will be the address of the first word.

Thus, the following two programs will generate the same code:

START:	MOVE 1,LIT
	JRST	.-1

LIT:	JRST	4,START
	END
-------------------------------------

START:	MOVE	1,[JRST 4,START]
	JRST	.-1
	END

A literal may embrace more that one line of text, and literals may be
used  recursively.   The  following  are examples of the legal use of
literals:
SAILON 26.2      FAIL MANUAL         FAIL STATEMENTS                9

	MOVE 1,[MOVE 2,[JRST 3]]
	FAD	3,[1.0]
	PUSHJ	P,[MOVE A,NUM
		   ADD B,TAB(A)
		   MOVEM B,(C)
		   POPJ	P,]
	MOVEI	A,[ASCIZ/ NOW IS THE TIME
/]
	JRST	[MOVE A, [ABCA-ZOT]
		 ADD	B,C
		 IDIV	B,[L-QRN]
		 JRST	.+1]

Note  that the symbol . retains its value in the main stream of code.
Thus the JRST .+1 in the last example above will return to  the  main
stream, i.e. to the instruction following the first JRST.  Labels may
be used inside the literals and will refer to the location where that
word of literal is finally stored.  In this case FOO: is not the same
as FOO←..

1.6 BLOCK STRUCTURE

FAIL  allows the programmer to use a form of block structure which is
quite similar to the traditional form.  The programmer is able to set
off  certain  sub-sets  of  his  program  as  blocks.   The assembler
considers the whole program proper as one  block,  and  this  is  the
outermost  block.   It  may  contain  a number of blocks, and each of
these may contain blocks.  There is no limit to the number of  blocks
a  program may or a block may contain.  There is, however, a limit to
the maximum depth of the block structure,  that  is,  the  number  of
blocks  which  can  be  nested  within one another.  This limit is 17
(decimal).

The purpose of block structure is to make possible the  multiple  use
of  the names of labels, op-defs, and macros.  If the definition of a
label, op-def, or  macro  occurs  inside  a  block,  that  definition
ordinarily  applies only inside that block and does not conflict with
definitions of labels, op-defs or opcodes of the same name  in  other
blocks.

Ideally,  if  a  label, op-def, or macro is defined in a given block,
that definition applies in that block, and that symbol is  considered
to be undefined in the block which the given block is part of, unless
it is defined separately in that (next-outer) block.  However, if the
given  block  has  a sub-block as part of it, that definition applies
within this (inner) block, unless the symbol has  another  definition
within  this (inner) block.  This is indeed the case with op-defs and
macros, except that forward references to macro and op-defs  are  not
permitted.   Thus,  if  it  is  desired  that  an  inner block have a
different definition of a macro or op-def  from  that  in  the  outer
block,  that  definition must be given in the inner block, before the
first reference to it in that block.  Otherwise,  the  definition  in
SAILON 26.2      FAIL MANUAL         FAIL STATEMENTS               10

the  outer  block will be used for those references to it which occur
before the inner block definition.   Labels do not have this problem,
since forward references to labels are permitted.

However,  there is another difficulty with labels in block structure,
which does not occur for op-defs and macros.  The difficulty is that,
for labels, there is an inherent connection between the value given a
label and the location in the program  at  which  the  definition  is
made. Thus it is not possible, with the ordinary mechanism, to define
a label as referring to an instruction in an inner block, and to make
the  definition  available  in  an  outer  block.  To get around this
difficulty, if a label definition or assignment statement is preceded
by  an  up-arrow  (↑),  that definition is made available to the next
outer block. (If the definition is preceded by  two  up-arrows  (↑↑),
the  definition  is  made available to all outer blocks).  This is as
though the definition had been made in the outer block,  except  that
the label cannot have a different value in the inner block.

An  inner  block  is  entered  with the BEGIN pseudo-op.  The current
block is ended with the BEND statement.   Thus a block is  surrounded
by  a  BEGIN  and  BEND.   For  details  of these pseudo-ops, see the
pseudo-op section.

Example of the use of block structure.  These two  programs  generate
the same code:

FOO1:	JRST	FOO1		FOO1:	JRST	FOO1
	JRST	FOO2			JRST	FOO2
	JRST	FOO3			JRST	FOO3
	BEGIN
FOO2:	JRST	FOO1		FOO22:	JRST	FOO1
↑FOO3:	JRST	FOO2		FOO3:	JRST	FOO22
	JRST	FOO3			JRST	FOO3
	BEGIN
	JRST	FOO1			JRST	FOO13
	JRST	FOO2			JRST	FOO22
	JRST	FOO3			JRST	FOO3
FOO1:	JRST	FOO4		FOO13:	JRST	FOO4
	BEND
↑FOO4:	JRST	FOO4		FOO4:	JRST	FOO4
	BEND
FOO2:	JRST	FOO4		FOO2:	JRST	FOO4


There is one other problem with block structure, and that has  to  do
with  the  accumulator  and index fields.  Since the assembler has no
way of knowing if a symbol will  be  defined  later  in  a  block,  a
reference  to  a symbol which has not been explicitly defined in this
block  must  be  treated  as  a  forward  reference  until  either  a
definition  or  the end of a block is encountered, even if the symbol
has a definition in the next-outer block.  Such symbols are  said  to
be  not  available,  even  though  they  are  defined.  Since forward
SAILON 26.2      FAIL MANUAL         FAIL STATEMENTS               11

references are not permitted in accumulator or  index  fields,  (i.e.
symbols in AC or index fields must be available) there are two kluges
by which it  is  possible  to  make  accumulator  symbols  explicitly
available  in  inner blocks, without the necessity of redefining them
in  each  block.   That  is,  there  are  two  ways  of  making  such
definitions  global.   One  of  these kluges is the GLOBAL pseudo-op,
which will not be discussed here (see pseudo-op section).  The other,
which is more useful in most cases, is the use of down-arrow (↓).  If
a label definition or assignment is preceded  by  a  down-arrow  (↓),
that  definition  will  be immediately available to any references to
the symbol in inner blocks. If a symbol which has been  defined  with
down-arrow  is  redefined  in an inner block, that redefinition holds
for that block only and does  not  affect  the  definition  in  outer
blocks.

SAILON 26.2      FAIL MANUAL           PSEUDO-OPS                  12

2.0	PSEUDO-OPS

2.1 DESTINATION OF ASSEMBLED CODE

As was stated earlier, the assembler uses a location counter to  keep
track  of  the location where the code it is assembling will go. This
counter is normally initialized to relocatable 0 at the start of  the
assembly and is incremented by 1 for each instruction assembled.  The
value in the location counter is the location  where  the  next  word
assembled  will  go.   The  contents  of  the location counter can be
changed with the LOC, RELOC, and ORG statements.

2.1.1 LOC

The LOC pseudo-op takes one operand, an  expression,  which  must  be
defined  (and  available).   The effect of LOC is to put the value of
the operand into the location counter and to set  the  relocation  of
the  counter  to  absolute  (regardless  of  the  relocation  of  the
argument).

2.1.2 RELOC

The RELOC statement has the same effect as the LOC  statement  except
that   the  relocation  is  set  to  relocatable  regardless  of  the
relocation of the argument.

2.1.3 ORG

The ORG statement has the same effect as the LOC or RELOC  statements
except that the relocation is set to the relocation of the argument.

Whenever LOC, RELOC or ORG is used, the current value of the location
counter is saved (along with its relocation).  A LOC, RELOC,  or  ORG
statement  with  no  argument  will  cause  the  preserved  value and
relocation to be put into (swapped with) the location counter.

2.1.4 Other Location Counters.

It is possible to have more than one location counter and  to  switch
back  and forth among them.  Location counters may be given any names
which fit the syntax of identifiers.  The SET pseudo-op  is  used  to
initialize  a location counter.  It takes two arguments. The first is
the name of the location counter and the second is the value to which
the  counter  should  be set.  The arguments should be separated by a
comma.  SET has the same effect as ORG except  that  it  changes  the
indicated  location counter and has no effect on the current location
counter unless it is the same as the indicated one.  SET  is  usually
used to create a new location counter.

The  USE pseudo-op is used to change location counters.  It takes one
argument, the name of the location counter to change to.  USE  causes
the  current location counter value to be saved away and the value of
SAILON 26.2      FAIL MANUAL           PSEUDO-OPS                  13

the indicated counter to be used.  If a subsequent USE indicates  the
location  counter  which was saved away, the value it had when it was
saved away will become the current value. Only the  currently  active
location  counter  is  incremented. If the indicated location counter
has not appeared before its appearance in a USE (i.e., if it  has  no
value),  it  will be given the value of the current location counter.
The location counter which the assembler starts with has a blank name
(i.e., a null argument indicates this first one).

Example:

Location:		Instructions:
     0'		  	 JRST FOO
     1'			 JRST BAZ
     2'			 SET GARP, 37
     2'			 USE GARP
     37			 JRST FOO
     40			 USE
     2'			 JRST FOO


Note: There is no relationship between location  counters  and labels
with  the  same name; just as there is no relationship between labels
and blocks with the same name.


2.1.5 Phase-Dephase

It  is  sometimes  desired  to  assemble code in one place which will
later be moved by the program itself to another place. In this  case,
it is desired that labels be defined as referring to locations in the
place where the code will be moved, rather than where  the  assembler
will put it.  To accomplish this, the PHASE pseudo-op is used.  PHASE
has one argument, the location to which the next word assembled  will
moved by the program. For instance, if, while the location counter is
at 74, a PHASE 32 appears, and a label appears on the next line,  the
label  will  be given the value 32, but the code on that line will be
placed in location 74.  The DEPHASE pseudo-op (no  argument)  cancels
the effect of any PHASE.


2.2 ENTERING DATA

The RADIX statement changes the prevailing radix until the next RADIX
statement is encountered.  It has no effect on numbers preceded by =.
The one argument of RADIX is interpreted in the current radix  unless
it  is  preceded  by  a =.  Thus, the statement RADIX 10 will have no
effect.  The radix may be set to  almost  anything, but  for  radices
above  10, there are no digits to represent 10, 11, etc. (Zero is not
permitted and 1 should  be  avoided  if  one  is  going  to  use  the
arithmetic FOR or Macro arguments with this radix ).

SAILON 26.2      FAIL MANUAL           PSEUDO-OPS                  14

2.2.2 DEC and OCT

The DEC and OCT statements each ake a string  of  arguments,  each  a
number,  separated  by commas.  The radix is temporarily set, for the
one statement, to 10 for DEC or 8 for OCT.  The numbers are placed in
successive locations.


2.2.3 BYTE

The BYTE statement is used to enter  bytes  of  data.   Arguments  in
parentheses  indicate  the  byte  size to be used until the next such
argument.  Other arguments are the Bytes.  An  argument  may  be  any
defined  (and  available)  expression. Arguments in parentheses (byte
size) are interpreted in decimal (base 10) and  other  arguements  in
the   prevailing   radix.    Bytes   are   deposited  with  the  byte
instructions, so if a byte will not fit in what's left of the current
word,  it  will be put in the left part of the next.  Unused parts of
words are filled with zeros.  Byte size arguments are not  surrounded
by  commas,  but  other  arguments  are  separated  by  commas.   For
instance, the statement

			BYTE (7) 3,5(11)6

will  put two seven bit bytes, (3 and 5) and an 11 (decimal) bit byte
(6) in a word, left justified.

The first  arguement  of  a  BYTE  statement  must  be  a  byte  size
arguement.  Two  successive  commas indicate a null argument which is
the same as 0.


2.2.4 POINT

The  POINT  pseudo-op  (2  or 3 arguments) assembles one word, a byte
pointer.   The  first  argument  should  be  an  expression  and   is
interpreted   in   decimal.   The  expression  must  be  defined  and
available.  It indicates the byte size and its value is placed in the
size field of the assembled word.  The second argument should contain
one or more of an index field, an address field, and an  at-sign  (@,
indirect).  The  last  (3rd)  field,  if  present,  indicates the bit
position of the low order  bit  of  the  byte,  i.e.,  its  value  is
subtracted from 35 (decimal) and placed in the position field.  It is
interpreted in decimal and must be available.  If the 3rd argument is
not  present  (no comma should be present in this case), the position
field is set to 36 (decimal), so that the first time the  pointer  is
incremented, it will point to the first byte of the word.


2.2.5 IOWD

IOWD is a permanently  defined macro.  Its definition is:
SAILON 26.2      FAIL MANUAL           PSEUDO-OPS                  15

     DEFINE IOWD (A,B)<
      XWD -A, B-1>


2.2.6 XWD

The XWD statement (2 arguments) assembles  a  single  word  with  the
value  of  the  first  argument in the left half and the value of the
second argument in the right half. Both arguments  must  be  present.
XWD  is  the  only way of creating a word with a forward reference in
the left half.


2.2.7 Text Statements

There  are  4  text  statements.   They  are ASCII, ASCIZ, ASCID, and
SIXBIT.  All take, as argument, a string of characters  starting  and
ending  with, and not otherwise containing, some non-blank character,
which serves as a delimiter.  This delimiter should not be  ←  or  :.
ASCII  puts  the 7-bit representation of each successive character in
the string (not the delimiter) in successive words, 5 characters  per
word,  until the string is exhausted.  The low order bit of each word
and the left-over part of the last word are filled with zero.   ASCIZ
is the same as ASCII, except that if the last character is the 5th of
a word, a word of zero is added at the end.  This is to  ensure  that
there is at least one 0 byte at the end.  ASCID works as ASCII except
that the low order bit of each word generated is a 1.   SIXBIT  works
as  ASCII  except  that  the  characters  are  converted to the 6-bit
representation and packed 6 to a word.  The low order bit is used  in
this representation and so is not necessarily zero.  The last word is
filled out with zeros if necessary. (ASCII is converted to SIXBIT  by
replacing the 40 bit with the 100 bit and removing the 100 bit.)

2.2.8 RADIX50

This  pseudo-op  has  one  or two arguments (separated by a comma, if
two). The second or only argument should be a symbol, and the  first,
if  present,  a number.  The value is the Radix50 for the symbol with
the number or'ed into the high order six bits.   The  two  low  order
bits of the number are cleared before oring.


2.3 BLOCK

The block statement takes one argument.  Its effect  is  to  add  the
value  of  the  argument to the location counter, thus reserving that
many locations.  The argument must be defined and available.

     BLOCK N

     is equivalent to
SAILON 26.2      FAIL MANUAL           PSEUDO-OPS                  16

     ORG . +N


2.4 ASSEMBLER CONTROL STATEMENTS


2.4.1 END

The END statement (1 argument) is the last statement of a program. It
signals the assembler to stop assembling and  no  text  following  it
will  be  processed.   The argument, if any, is taken as the starting
address of the program.  All outstanding variables and  literals  are
placed starting at the current value of the location counter when the
END is seen.  (See below.  Variables are symbols which appeared  with
a #).  Variables are put out first.


2.4.2 LIT

The LIT statement causes all literals which were defined  up  to  the
LIT  statement  to be placed where the LIT statement occurs.  The LIT
statement must not appear inside a literal.


2.4.3 VAR

The  VAR  statement causes all variables (variables are symbols which
were defined by having a #  after  one  or  more  appearances)  which
appeared  with  a  # in this block (or a sub-block of this one) to be
placed where the VAR appears.  VAR must not appear inside a literal.


2.4.4 TITLE

This  statement  should  be  followed  by a string of characters, the
first part of which should be an identifier.  That identifier is then
used  as the program name which DDT will recognize.  It is also taken
as the name of the outer-most block.  The  string  of  characters  is
printed  as  a part of the heading to all pages subsequent to the one
on which the TITLE statement appears.  There should be only one TITLE
statement  per program.  The title statement should appear before any
statement which generates code.


2.4.5 SUBTTL

This  statement  should  be followed by a string of characters.  That
string is then used as a sub-heading on all  subsequent  pages  until
another SUBTTL appears.

Note:  The string to be used in  the  heading  for  either  TITLE  or
SUBTTL is terminated by  the first carriage-return or semi-colon.
SAILON 26.2      FAIL MANUAL           PSEUDO-OPS                  17

2.4.6 BEGIN, BEND

The BEGIN statement is used to start a block.  The  block  it  starts
will  end  at  the  corresponding  BEND  statement.  The BEGIN may be
followed by an identifier.  If it is, the identifier will be taken as
the  name  of  that block, which DDT will recognize. If no identifier
appears, the assembler will  create  one.   All  text  following  the
identifier  and  all  text  after BEND in a BEND statement is ignored
until the next line-feed.  For a discussion of block  structure,  see
that section in the first chapter.


2.4.7 PAGE

This pseudo-op has the same function as a  form-feed.   It  causes  a
form-feed  to  be placed in the listing immediately following itself.
The effect is to skip to the top of the next page of listings.


2.4.8 LIST-XLIST

The  XLIST  statement  causes  listing  to  stop  until the next LIST
statement.  LIST causes listing to resume if it has been  stopped  by
an XLIST or XLIST1 statement.  Otherwise it is ignored.


2.4.9 XLIST1

This statement has exactly the same effect as  XLIST  unless  the  /I
switch was used in the command string, in which case it is ignored.

2.4.9.5 XCREF - CREF

These turn off and on the emition of information to CREF.  They  have
no effect if /C was not used in the command string.


2.4.10 LALL-XALL

XALL  causes  the listing of the body of Macros, Repeats, and Fors to
stop; LALL causes it to start up again.

2.4.10.5 NOLIT

This has the same effect as /L in the command string.

2.4.11 OPDEF

The OPDEF statement has the following strange syntax:

     OPDEF symbol [value]
SAILON 26.2      FAIL MANUAL           PSEUDO-OPS                  18

The  syntax  is  strange  for  compatability  with existing, inferior
assemblers.  The effect of OPDEF is to insert  the  symbol  into  the
op-code table  with the indicated value.  The symbol may then be used
as any other op-code.  Note that the value may have  bits  in  fields
other  than the op-code field.  In this case, these bits will be ored
with bits which are indicated where the symbol is used, in  the  case
of  the  AC,  index  or  indirect fields.  In the case of the address
field, any indicated address will replace the one in the OPDEF.   The
value part of the OPDEF must be defined and available.


2.4.12 EXTERNAL

EXTERNAL must be followed by a list of symbols separated  by  commas.
The effect is to tell the assembler that these symbols are defined in
a different program and are declared INTERNAL (see below) there.  The
loader  will then fix up the references to these symbols when the two
programs are loaded.  EXTERNAL symbols must not  be  defined  in  the
program in which they are external.


2.4.13 INTERNAL

This statement declares that certain symbols should be made available
to other programs by the loader.  See EXTERNAL above. INTERNAL should
be followed by a list of symbols.  These symbols need not necessarily
be  defined  before  the INTERNAL statement appears, but they must be
defined by the end of the program.

2.4.13.5 ENTRY

If used, this statement must appear before all other  statements.  It
has  the  same  format and the same effect as INTERNAL except that it
emits special library entry blocks to the loader.

2.4.14 COMMENT

The first non-blank character following the COMMENT op-code is  taken
as the delimiter.   All text from it to the line-feed  following  the
next   occurrence  of  this  delimiter  is  totally  ignored  by  the
assembler.


2.4.15 GLOBAL

The  global  pseudo-op  should  be  followed  by  a  list  of symbols
separated by commas.  Each symbol  should  be  defined  in  an  outer
block.   The effect of GLOBAL is to find te next outer block in which
that symbol is defined and to  make  the  definition  in  that  block
immediately  available  in  the  block  in  which the GLOBAL appears.
GLOBAL  does  not  affect  the  definition  of  the  symbol  in   any
intervening blocks.
SAILON 26.2      FAIL MANUAL           PSEUDO-OPS                  19

If  a  symbol  has been declared GLOBAL in the current block, and the
symbol is then redefined in this block,  that  redefinition  is  made
also  on  the  definitions  in the outer block where GLOBAL found the
definition.  Doing this causes strange effects if the definition  was
not  in  the  next-outer block and it should not be done without some
careful thought.

2.4.16 LINK-LINKEND

The format is LINK(END) number, location.  These pseudo-ops  generate
loader block type 11.  See Sailon 46 for more information.

2.4.17 INTEGER

This  pseudo-op  should be followed by a string of symbols, separated
by commas.  Each of these symbols is then treated as  though  it  had
appeared in the block where the INTEGER appears, followed by a #.

2.4.18 ARRAY

The  format  is  ARRAY  symbol  [number],.....   This is like INTEGER
except that "number" locations are set aside as a block, symbol being
the address of the first one.

2.5  PRE-DEFINED OP CODES

The usual op-codes of the PDP-10 are defined in FAIL.   In  addition,
many  of  the  UUO's or IOT's mentioned in the monitor manual (Sailon
55) are defined in FAIL.  These are:

1. Standard DEC system UUO's.
	INIT ENTER LOOKUP USETO USETI UGETF MTAPE RELEAS CLOSE OUTBUF
	INBUF CALLI CALL STATO STATZ GETSTS SETSTS OPEN RENAME IN OUT
	INPUT OUTPUT

2. Stanford general.
	SPCWAR UINBF UOUTBF FBREAD FBWRT MAIL SEND WRCV SRCV SKPME
	SKPHIM

3. Stanford displays.
	DPYCLR DPYPOS DPYSIZ DPYOUT UPGIOT UPGMVM UPGMVE
	PPSEL PPACT PPREL PGIOT PGSEL

4. Stanford teletype.
	TTYUUO TTCALL INCHRW INCHRS OUTCHR OUTSTR INCHWL INCHSL 
	GETLIN SETLIN RESCAN CLRBFI CLRBFO INSKIP

5. Stanford pseudo-teletype.
	PTYUUO PTYGET PTYREL PTIFRE PTOCNT PTRD1S PTRD1W PTWR1S
	PTWR1W PTRDS PTWRS7 PTWRS9 PTGETL PTSETL PTLOAD

SAILON 26.2      FAIL MANUAL          MACROS (etc)                 20

3.0	MACROS (etc)

Macros  are  strings  of  text,  with  names,  and,  optionally, with
substitutable arguments.  They are used where  the  same  or  similar
pieces of text (code) are used in several places.  A macro is defined
with the DEFINE statement.  An example of its format is:

	DEFINE FOO (AC,ADDRS)
	{MOVNI	AC,-3
	 IMUL	AC,ADDRS
	 ADDI	AC,37
	 MOVEM	AC,ADDRS}

(< and > may be used in place of { and } ).

The effect of ths statement is that the assembler will store the text
between the { and the matching } in  its  memory  and,  whenever  the
identifier  FOO  appears,  the string of text will be substituted for
it.  Also, the arguments which follow the occurance of  FOO  will  be
subsitiuted  in  the  string  of text where AC and ADDRS appear.  For
example, if:

	FOO (3, FARB+7 )

appears  in  the  program  somewhere  after the DEFINE above, it will
expand into the following:
	
	MOVNI	3,-3
	IMUL	3,FARB+7
	ADDI	3,37
	MOVEM	3,FARB+7

The  arguments  to  a macro call (the 3, FARB+7 in the above example)
may be enclosed in parentheses (as above) or not.  Thus:

	FOO 3,FARB+7

would have the same effect.

3.1 MACRO BODY

The  body  of a macro (the text part) may be any string of characters
with the one restriction that the right and left curly brackets  ({})
must be balanced (and the occurances of < and > must be balanced).

3.2 ARGUMENTS in definition.

Arguments  in macro definitions must be identifiers.  A list of them,
enclosed in parentheses, must appear after  the  macro  name  in  the
definition.    Any   intervening   text  is  ignored,  except  for  a
concatenation character (see below).  If no list of arguments appears
before the macro body, it is assumed that there are no arguments.
SAILON 26.2      FAIL MANUAL          MACROS (etc)                 21

Everywhere an identifier appears in the text (body) which is the same
as one of the arguments, that identifier will be  replaced  with  the
string  of  text which corresponds to that argument when the macro is
called.  Thus, if FUDLY is one of the arguments in the definition  of
a macro, and the following appears in the body:

	A+FUDLY B

the FUDLY will be recognized as an argument.  But  if  the  following
appears:

	A+FUDLYB

then, since FUDLYB is an identifier and is different from  FUDLY,  it
will  not  be  recognized  as  an  argument.   For inserting parts of
identifiers as arguments, see "concatenation" below.

3.3 Concatenation.

If a non-blank character other than a  left  parenthesis  or  a  left
curly  bracket  or  broket  ( ( or { or < ) except carriage return or
line feed appears after the macro name in the definition, it is taken
as  the  concatenation character.  This character may then be used to
delimit identifiers so that they will  be  recognized  as  arguments.
Appearances  of this character will be deleted from the macro body if
they are immediately preceded or  followed  by  an  argument  of  the
macro.

3.4 MACRO Calls

A macro name may appear anywere and will be expanded to the MACRO, as
long as the name appears as an identifier and  is  considered  as  an
identifier  by  the  assembler.   (There are a few exceptions, listed
below). Thus, if FOO is a macro, it may appear alone on  a  line,  in
the AC or index field or address filed, etc.  However, if FOO appears
in a comment, or in the text argument of an ASCII statement, etc., it
will   not  be  expanded,  because  it  will  not  be  considered  an
identifier.  Exceptions to this  are  the  macro  name  in  a  DEFINE
statement,  the  symbol  name  in  an OPDEF statement, and the formal
parameter list (list of arguments) in a DEFINE; macro names are never
expanded in these places.

Macros  may be used recursively, that is, a macro may contain a macro
call or macro definition.  However, if such macro  calls  are  nested
too  deep,  the  macro  push-down  list  may overflow, resulting in a
monitor  error message and terminating the assembly.  If this occurs,
the /P switch should be used in the command string.  Every occurrence
of /P in the command string causes the assembler to allocate an extra
200 (octal) words of memory for the macro push-down list.
SAILON 26.2      FAIL MANUAL          MACROS (etc)                 22

3.5 ARGUMENTS in macro calls.

Note:  in  the  following  discussion, right square bracket and right
broket ( ] and > ) will have the same effect as carriage return.

The list of arguments to a macro call may be enclosed in parentheses.
The arguments themselvs are separated by commas.  The first  argument
to  the macro starts with the first character (including blank) after
the left parentheses, if the arguments are enclosed in parentheses or
with  the first non-blank character after the macro name, if they are
not. Subsequent arguments start with the  first  character  (inluding
space)  after  the  comma  which terminates the argument before.  All
arguments terminate with the last character before the next comma, or
the  right parenthesis if parentheses are used, or the first carriage
return or semicolon if parentheses are not used.   Two  commas  in  a
row, with no characters in between, indicate a null argument, i.e. an
argument consisting of no  characters.   The  right  parenthesis,  if
parentheses  are used, or the first carriage return, if they are not,
terminates the argument string.  If more  arguments  are  called  for
than  are  supplied,  the  last ones are considered to be null (i.e.,
consist of no characters).  If more arguments are supplied  than  are
called for, the extras are ignored by the macro processor.  (See "How
much is eaten" below.)

There  are two exceptions to the above.  If the first character of an
argument is a left curly bracket ({) or broket (<), all characters up
to  the  matching  right  bracket  (}) or broket (>) are taken as the
argument.  In this way the argument may contain commas,  parentheses,
etc.,  the only restriction being the balancing of the curly brackets
or brokets.  The curly brackets  (outer  pair)  or  brokets  are  not
included  as  part of the argument.  All characters between the right
curly bracket (}>) which ends the argument,  and  the  next  argument
terminator  (comma,  or  carriage  return if no parentheses, or right
parenthesis if parentheses) are ignored. In this way it  is  possible
to  continue  a  list  of  arguments  from one line to the next (i.e.
enclose the last argument on the line in curly brackets and  put  the
comma for it at the start of the next line.)

The other exception occurs if the first character of an argument is a
right arrow (→) (Note: the character back slash ( ) may be  used  for
the  right  arrow  in teletype-prepared text.) In this case, the next
thing after the right arrow is considered to be an expression (and it
better  be).  The expression is evaluated (it better be defined, too)
and the value is converted to a string of ascii digits in the current
radix (radix hadn't ought to be 1). This string of digits is taken as
the argument.  All characters from the end of the expression  to  the
next argument termination character (comma etc) are ignored.
SAILON 26.2      FAIL MANUAL          MACROS (etc)                 23

3.6 How much is eaten.

When  a macro call appears, a certain amount of text is considered as
being part of the call, while the rest is not, and will be assembled.
For instance if:

	DEFINE FOO (A) { A + 7/6}

has appeared, then when:

	MOVEI	A,FOO (3) (6) ; comment

appears, it will be assembled as:

	MOVEI	A,3+7/6 (6)  ; comment

Thus, the text FOO (3) is considered to be part of  the  macro  call,
and is "eaten".

A  definite,  if  complicated, set of rules govern how much text gets
eaten in a macro call.   If  the  macro  was  defined  as  having  no
arguments,  then  only  the  macro  name and any following spaces (or
tabs) are eaten. If the macro was defined as  having  arguments,  and
the   first   non-blank   character   after   the  macro  name  is  a
left-parenthesis, then everything from the macro name  to  the  right
parenthesis which  closes  the argument list, inclusive, is eaten. If
the macro was defined as having arguments  and  the  first  non-blank
character  is  not a left parenthesis, then everything from the macro
name, to the comma or carriage return which terminates the last macro
argument  used,  is eaten.  Thus, if parentheses are not used and too
few arguments are supplied, everything from the  macro  name  to  the
carriage  return will be eaten.  If parentheses are not used, and the
macro was defined  as  having  arguments,  and  enough  or  too  many
arguments  are  supplied, everything from the macro name to the comma
(or carriage return) which terminates the last argument used, will be
eaten.

	Example -- if:

	DEFINE FOO $(A,B) {A$B}

	then:

	MOVEI FOO 1,2,  ,37(6)

	will expand to:

	MOVEI 12,37(6)

	and the "FOO 1,2, " will have been eaten.
SAILON 26.2      FAIL MANUAL          MACROS (etc)                 24

3.7 FOR

The FOR statement serves, among other purposes and in a more  general
and  useful  way,  the same purpose that is poorly served in inferior
assemblers by the IRP and IRPC messes.  There are  3  types  of  FOR;
they  all  have  the  same general form. They start with the word FOR
followed by a range specifier, followd by a string of  text  enclosed
in  curly  brackets and called the "argument list".  The text has the
same form as the body of a macro,  and  the  FOR  expands  into  that
string  of  text,  repeated once for each element in the range of the
FOR.  The FOR may have  one  or  two  "formal  arguments"  which  are
specified  in  the  range  specification.   The  FOR  may also have a
concatenation character.  If a concatenation character is desired, it
is  specified by following the word FOR with the character @ followed
immediately by the concatenation character.  Note that if  a  FOR  is
used  inside  a macro, and concatenation of FOR arguments is desired,
it is necessary to have a concatenation character specified  for  the
FOR (which is different from the one for the macro, if any).

3.7.1 "IN" FOR

This  is  the type of FOR which replaces the outmoded IRP.  The range
specification consists of one or  two  formal  argument  identifiers,
followed  by either the identifier IN or the character ⊂, followed by
an argument list. The argument list has the same syntax  as  a  macro
argument  list,  except  that  the  list must be in parentheses.  The
effect is that the body of the FOR is assembled once for each element
in  the  argument list, and that element is substituted for the first
(or only) formal argument each time.  The second formal argument,  if
present,  will have the remainder of the argument list (starting with
the element following the one currently  substituted  for  the  first
argument) substituted for it.

	Examples:

	FOR A IN (QRN,{(<JRST 4,>)} STORP)
	{MOVSI 13,A
	 PUSHJ	P,GORP
	}

	will expand to:

	MOVSI	13,QRN
	PUSHJ	P,GORP
	MOVSI	13,(<JRST 4,>)
	PUSHJ	P,GORP
	MOVSI	13,STORP
	PUSHJ	P,GORP

	------------------------------
	FOR ZOT,FUB ⊂ (A,B,C,D)
	{ MOVEI ZOT,137 ; FUB LEFT
SAILON 26.2      FAIL MANUAL          MACROS (etc)                 25

	}

	will expand to:

	MOVEI	A,137 ; B,C,D LEFT
	MOVEI	B,137 ; C,D LEFT
	MOVEI	C,137 ; D LEFT
	MOVEI	D,137 ; LEFT

3.7.2 Character FOR

This type of FOR replaces IRPC.  The range specifier consists of  one
or  two  formal  arguments  followed  by  either  the letter E or the
character ε, followed by a string of  characters  enclosed  in  curly
brackets.  The  only  restriction on the string of characters is that
the curly brackets must balance.  The body of the  FOR  is  assembled
once  for each character in the list, with that character substituted
for the first formal argument each time, and the rest of  the  string
(CDR) substituted for the second formal argument, if any.

	Examples:

	FOR ZOT,FUB ε {ABCD}
	{ MOVEI ZOT,137 ; FUB LEFT
	}

	will expand to:

	MOVEI	A,137 ; BCD LEFT
	MOVEI	B,137 ; CD LEFT
	MOVEI	C,137 ; D LEFT
	MOVEI	D,137 ; LEFT
	---------------------------------
	FOR @$ QRN ε {AZ1Q5}
	{ZORP$QRN←0
	}

	will expand to:

	ZORPA←0
	ZORPZ←0
	ZORP1←0
	ZORPQ←0
	ZORP5←0

3.7.3 Arithmetic FOR

This type of FOR is similar to the ALGOL FOR.   The  range  specifier
consists  of one or two formal arguments followed by a left arrow (←)
followed by two or  three  expressions,  separated  by  commas.   The
expressions  are  like  the  two  or  three arguments of a FORTRAN DO
statement.  The value of the first is the starting value,  the  value
SAILON 26.2      FAIL MANUAL          MACROS (etc)                 26

of  the second is the ending value, and the value of the third is the
increment.  If the third expression is not present, the increment  is
taken  as  1.  The body of the FOR is assembled repeatedly, first for
the starting value, then for the starting value plus  the  increment,
etc.  until  it  has been assembled once for each such value which is
less than or equal to the ending value. (Greater than or equal if the
increment is negative.) If the starting value is already greater than
the ending value (less than, for negative increment), the FOR body is
not   assembled   at   all.    For   each   repetition,  the  current
(corresponding) value is converted to ascii  digits  in  the  current
radix,  and  that  string  is  substituted  for  the  formal argument
(arguments).  Note that all expressions must be  defined,  available,
and not relocatable.

	Examples: (assume base 8)

	FOR I←1+3, 25, 7
	{ XWD FOO,I
	}

	will expand to:

	XWD FOO,4
	XWD FOO,13
	XWD FOO,22

	-------------------------------------

	FOR @$ ZOT←4,11
	{ZOTQ$ZOT : ZOT +3
	}

	will expand to:

	ZOTQ4 : 4 +3
	ZOTQ5 : 5 +3
	ZOTQ6 : 6 +3
	ZOTQ7 : 7 +3
	ZOTQ10 : 10 +3
	ZOTQ11 : 11 +3

3.8 REPEAT

For compatibility with a certain  existing  inferior  assembler,  the
REPEAT statement is included.  The format is:

	REPEAT n, { text }

where n is any defined available expression and the text  is  like  a
macro  body.   The  expression is evaluated and the text is assembled
that number of times, with a carriage return-line  feed  inserted  at
its end each time.
SAILON 26.2      FAIL MANUAL          MACROS (etc)                 27

	Example:

	REPEAT 3, {0}

	will expand to:

	0
	0
	0

3.9 Conditional Assembly.

The conditional  assembly  op-codes  (the  IF's)  differ  from  other
pseudo-ops  in  that,  like macros, they will be recognized as the IF
op-codes wherever they appear, as long as the assembler sees them  as
identifiers.  Thus, IF's need not be the first things on lines.

3.9.1 Numeric IF's.

There are six numeric IF's.  They are:

	IFE, IFN, IFG, IFL, IFGE, IFLE

They stand for, respectively, if equal,  if  not  equal,  if  greater
than,  if  less  than,  if  greater than or equal to, if less than or
equal to. The format is as follows:

	IFE exp, { text }           or
	IFE exp, < text >

The  expression  is  evaluated,  and if its value bears the indicated
relation (in this case equal) to zero, the text  is  assembled  once;
otherwise  it  is  not  assembled, and does not appear as part of the
program.  The text is like  a  macro  body  --  {}  and  <>  must  be
balanced.

	Examples:

	IFE 3, {ZOT}

	will be skipped, but

	IFGE 15, {JRST START}

	will expand to:

	JRST	START

3.9.2 Text IF's

There are two text IF's.  They are IFIDN and IFDIF which stand for if
identical and if different, respectively.  The format is:
SAILON 26.2      FAIL MANUAL          MACROS (etc)                 28

	IFIDN {text 1} {text 2} {text 3}

(<>  are  substitutable  for the {}).  The texts can be any string of
characters in  which  the  curly  brackets  (or  pointy  brackets  or
brokets) balance. For IFIDN, if the two strings text 1 and text 2 are
identical in each and every character, the  string  text  3  will  be
assembled,  otherwise  it  will not.  For IFDIF, if text 1 and text 2
are identical, text 3 will not be assembled, otherwise it will.

3.9.3 Symbol IF's.

There are eight symbol IF's.  There are IFDEF, IFNDEF, IFAVL, IFNAVL,
IFOP, IFNOP, IFMAC, IFNMAC.  The format for these is:

	IFDEF symbol, {text}

If  the  indicated  condition  is  true  for  the symbol, the text is
assembled. Otherwise it is not.  The ops come in pairs; if the  first
of  a  pair  is true, the second is false, if the first if false, the
second is true. IFDEF will be true if the symbol  is  defined  as  an
op-code  (OPDEF), or as a macro, or if it has been defined as a label
(colon or left arrow) in this block or  an  outer  block.   In  other
words,  IFDEF  will  be true if the symbol could be used on a line by
itself  (ignoring  possible  future  definitions).   IFNDEF  is   the
opposite  of IFDEF. IFAVL will be true if the symbol is defined as an
op-code or macro or if it has been defined in this block, or declared
global  in  this  block  and  defined in an outer block, or if it was
defined in an outer block with a down-arrow.  In other  words,  IFAVL
will  be  true  if  the symbol is immediately available. IFOP will be
true if the symbol is defined as an op-code.  IFMAC will be  true  if
the symbol is defined as a macro.



SAILON 26.2      FAIL MANUAL                                       29

			APPENDIX  I       	
   		      COMMAND LANGUAGE

The basic format of a FAIL command is:

	binary_file,listing_file ← source_file

File specifications consist of:

	device : file

If device: is missing, DSK: is assumed.  Either the binary or listing
file may be omitted (or both).  If the listing is omitted, the  comma
may  be  omitted  too;  if  the  binary is omitted, the comma must be
present.

Switches should follow file names and may  be  either  of  the  slash
(e.g. "/x" ) or parens type (e.g. "(x)").

There  are  three  types  of switches: those that affect a device, in
which case the switch should appear after the name of the file to  be
affected;  those  that  affect  the  operation  of the assembler as a
whole, in which case the switch may follow any file name; and the "P"
switch, discussed below.

Device-affecting switches:
	
	N	no listing of errors on TTY
	R	wait after each error as it is printed on TTY
	S	list symbol table
	I	ignore XLIST1
	L	don't list literal values with text.
	C	make a cref
	U	underline macro expansions on listing
	Q	do not convert character set on listing.
	J	turn on creffing
	K	turn off creffing

"P" switch:  The macro push-down list is normally 200 locations long.
If a lot of recursion is used in macros, this may not be enough.  The
macro PDL will be expanded by 200 words for every occurrence of the P
switch  in  the  command  string.   Alternatively  (#P)  where # is a
number, may be used.  For instance the following two  will  have  the
same effect:

	/P/P/P
	(3P)